package com.zh.modules.app.interceptor;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import static com.alibaba.fastjson.serializer.SerializerFeature.IgnoreNonFieldGetter;

/**
 * 打印方法日志
 */
@Aspect
@Component
@Slf4j
public class LogRecordAspect {

    /**
     * 定义切点Pointcut
     */
    @Pointcut("execution(* io.linfeng.modules.app.controller..*.*(..))")
    public void excludeService() {
    }

    /**
     * 执行切点 之前
     */
    @Before("excludeService()")
    public void exBefore() {
    }

    /**
     * 通知（环绕）
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("excludeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        Object[] args = pjp.getArgs();
        String params = "";
        try {
            //获取请求参数集合并进行遍历拼接
            if (args.length > 0) {
                if (HttpMethod.POST.name().equals(method)) {
                    params = JSON.toJSONString(getKeyAndValue(args), IgnoreNonFieldGetter);
                } else if (HttpMethod.GET.name().equals(method)) {
                    params = request.getQueryString();
                }
            }
        } catch (Exception e) {
            log.warn(e.toString());
        }
        Object result = pjp.proceed();
        long time = System.currentTimeMillis() - start;
        log.info("request end --------- uri:{}, method:{}, params:{}, result={},spendTime:{}", uri, method, params, JSON.toJSONString(result), time);
        return result;
    }

    /**
     * 执行切点之后
     */
    @After("excludeService()")
    public void exAfter() {
    }

    /**
     * 解析post请求的body
     *
     * @param objs
     * @return
     */
    public static Map<String, Object> getKeyAndValue(Object[] objs) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>(16);
        if (!ObjectUtils.isEmpty(objs)) {
            for (Object object : objs) {
                // 得到类对象
                Class<?> userCla = object.getClass();
                /* 得到类中的所有属性集合 */
                Field[] fs = userCla.getDeclaredFields();
                for (Field f : fs) {
                    if ("request".equalsIgnoreCase(f.getName())) {
                        continue;
                    }
                    // 设置些属性是可以访问的
                    f.setAccessible(true);
                    Object val = f.get(object);
                    // 得到此属性的值
                    map.put(f.getName(), val);
                }
            }
        }
        return map;
    }
}
